﻿using Dispatch.Receive;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dispatch.DispatchData
{

    /// <summary>
    /// 存在修改，不能使用struct
    /// </summary>
    public class WaringArea
    {
        public string AreaID { get; set; } = "";
        public List<PointF> PointList { get; set; } = new List<PointF>();

        public int MaxX { get; set; }
        public int MaxY { get; set; }

        public int MinX { get; set; }
        public int MinY { get; set; }

        public bool Locked { get; set; }

        /// <summary>
        /// 封锁交管区的AGV
        /// </summary>
        public int Owner { get; set; }


        public List<int> StopList { get; set; }= new List<int>();
    }


    /// <summary>
    /// 上锁的简要标识
    /// </summary>
    public struct WaringAreaState
    {
        public string AreaID { get; set; }  
        public bool Locked { get; set; } 
    }



    /// <summary>
    /// 区域汇总数据，只读，使用struct
    /// </summary>
    public struct AreaSynthesisInfo
    {

        public string AreaID { get; set; }


        public bool Locked { get; set; }

        /// <summary>
        /// 封锁交管区的AGV
        /// </summary>
        public int Owner { get; set; }


        public string LockedAgv;
    }



    public class WarningAreaDataSet
    {

        static   List<WaringArea> areaList=new List<WaringArea>(); 

        public static void FillData(List<WaringArea> list)
        {
            lock (areaList)
            {
                areaList.Clear();
                areaList.AddRange(list);
 
            } 
        }
 


        /// <summary>
        /// 判断是否进入了区域内
        /// 如果是第一个进入，自动上锁
        /// </summary>
        /// <param name="AgvID"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <returns></returns>
        public static Task<WaringAreaState> CheckArea(int AgvID, int X,int Y)
        {
            WaringAreaState result = new WaringAreaState()
            {
                AreaID = "",
                Locked = false,
            };
            //快速过滤不相干的区域，没必要每个区域都来IsInPolygon
            var tmplist = areaList.Where(p => p.MaxX >= X && X >= p.MinX && p.MaxY >= Y && Y >= p.MinY).ToList();
            if(tmplist.Count == 0)
            {
                return Task.FromResult(result);
            }

            PointF current = new PointF(X, Y);
            foreach (var tmp in tmplist)
            { 
                if (IsInPolygon(current, tmp.PointList))
                {
                    //在区域内
                    if (tmp.Locked)
                    {
                        if(tmp.Owner == AgvID)
                        {
                            //区域没有重复的，而且这个区域是这个AGV锁住的 
                        }
                        else
                        {
                            //被其它AGV锁住了
                            result.AreaID = tmp.AreaID;
                            result.Locked = true;
                        }
                       
                    }
                    else
                    {
                        //没上锁,此时锁住，
                        lock (areaList)
                        {
                             for(int i = 0; i < areaList.Count; i++)
                            {
                                if(areaList[i].AreaID == tmp.AreaID)
                                {
                                    areaList[i].Locked = true;
                                    areaList[i].Owner = AgvID;
                                    break;
                                }
                            } 
                        }
                        result.AreaID = tmp.AreaID;
                        result.Locked = false;
                    } 
                    //只需要判断一次在不在区域内即可
                    break;
                }

            }
            return Task.FromResult(result);
        }

        /// <summary>
        /// 进入停下来的列表
        /// </summary>
        /// <param name="AgvID"></param>
        /// <param name="AreaID"></param>
        /// <returns></returns>
        public static Task AgvStopAsync(int AgvID,string AreaID)
        {
            lock (areaList)
            {
                var tmp = areaList.Find(x => x.AreaID == AreaID);
                if(tmp != null)
                {
                    tmp.StopList.Add(AgvID);
                }
            }
            return Task.CompletedTask; 
        }


        /// <summary>
        /// 释放交管区域
        /// </summary>
        /// <param name="AreaID"></param>
        /// <returns></returns>
        public static Task ReleaseAsync(string AreaID)
        {
            lock (areaList)
            {
                var tmp = areaList.Find(x => x.AreaID == AreaID);
                if (tmp != null)
                {
                    if(tmp.StopList.Count> 0)
                    {
                         
                        int agvid = tmp.StopList[0];
                        tmp.StopList.RemoveAt(0);
                        //更换上锁者
                        tmp.Owner = agvid;
                       

                        //启动agv
                        byte[] buf = AgvEvent.Traffic(agvid,Stop:false);
                        _=AgvDataSet.SendToAgvAsync(agvid,buf);
                    }
                    else
                    {
                        //直接解锁
                        tmp.Owner = 0;
                        tmp.Locked = false;
                    }
                    _=ToCacheAsync(tmp);
                }
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 释放某个AGV占用的区域
        /// </summary>
        /// <param name="AgvID"></param>
        /// <returns></returns>
        public static Task ReleaseByAgvAsync(int AgvID)
        {
            lock (areaList)
            {
                var tmp = areaList.FindAll(x => x.Owner == AgvID || x.StopList.Contains(AgvID) );
                if (tmp != null)
                {
                    foreach(var item in tmp)
                    {
                        if(item.Owner == AgvID)
                        {
                            #region 同Release，但是因为有锁，所以不能直接调用
                            if (item.StopList.Count > 0)
                            {
                                int agvid = item.StopList[0];
                                item.StopList.RemoveAt(0);
                                //更换上锁者
                                item.Owner = agvid;
                                //启动agv
                                byte[] buf = AgvEvent.Traffic(agvid, Stop: false);
                                _ = AgvDataSet.SendToAgvAsync(agvid, buf);
                            }
                            else
                            {
                                //直接解锁
                                item.Owner = 0;
                                item.Locked = false;
                            }
                            #endregion
                        }
                        else
                        {
                            item.StopList.Remove(AgvID);
                        }
                    } 
                }
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// AGV锁住的区域
        /// </summary>
        /// <param name="AgvID"></param>
        /// <param name="AreaID"></param>
        /// <returns></returns>
        public static Task SetAgvAreadIDAsync(int AgvID, string AreaID)
        {
            lock (areaList)
            {
                var tmp = areaList.Find(x => x.AreaID == AreaID);
                if(tmp != null)
                {
                    tmp.Owner = AgvID;
                } 
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 获取AGV锁定的区域ID
        /// </summary>
        /// <param name="AgvID"></param>
        /// <returns></returns>
        public static Task<string> GetAreaIDOfAgv(int AgvID)
        {
            lock (areaList)
            {
                string? tmp = areaList.Where(x => x.Owner == AgvID).Select(x=>x.AreaID).FirstOrDefault(); 
                if(tmp != null)
                {
                    return Task.FromResult(tmp);
                }
                else
                {
                    return Task.FromResult("");
                }
                
            }
        }


        /// <summary>
        /// 判断点是否在多边形内
        /// </summary>
        /// <param name="checkPoint"></param>
        /// <param name="polygonPoints"></param>
        /// <returns></returns>
        public static bool IsInPolygon(PointF  checkPoint, List<PointF> polygonPoints)
        {
            int counter = 0;
            int i;
            double xinters;
            PointF p1, p2;
            int pointCount = polygonPoints.Count;
            p1 = polygonPoints[0];
            for (i = 1; i <= pointCount; i++)
            {

                p2 = polygonPoints[i % pointCount];
                if (checkPoint.Y > Math.Min(p1.Y, p2.Y)//校验点的Y大于线段端点的最小Y
                    && checkPoint.Y <= Math.Max(p1.Y, p2.Y))//校验点的Y小于线段端点的最大Y
                {
                    if (checkPoint.X <= Math.Max(p1.X, p2.X))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断).
                    {
                        if (p1.Y != p2.Y)//线段不平行于X轴
                        {
                            xinters = (checkPoint.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
                            if (p1.X == p2.X || checkPoint.X <= xinters)
                            {
                                counter++;
                            }
                        }
                    }

                }
                p1 = p2;
            }

            if (counter % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }



        #region 写缓存

        static   Task ToCacheAsync(WaringArea obj)
        {
            //操作
            return Task.CompletedTask;
        }


        #endregion

        #region 监控

        /// <summary>
        /// 监控用，获取所有传输坞的信息、物料状态、最后的指令
        /// </summary>
        /// <returns></returns>
        public static Task<List<AreaSynthesisInfo>> GetAllInfoAsync()
        {
            List<AreaSynthesisInfo> list = new List<AreaSynthesisInfo>();
            areaList.ForEach(item =>
            {
                AreaSynthesisInfo obj = new AreaSynthesisInfo();
                obj.AreaID = item.AreaID;
                obj.Locked = item.Locked;
                obj.Owner = item.Owner;
                
                if(item.StopList != null&& item.StopList.Count > 0)
                {
                    obj.LockedAgv = string.Join(",", item.StopList);
                }
                else
                {
                    obj.LockedAgv = "";
                } 
                list.Add(obj);
            });

            return Task.FromResult(list);
        }



        #endregion
    }
}
